home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 2000
/
MacHack 2000.toast
/
pc
/
The Hacks
/
Vertigo
/
RenderEngine
/
FlushPort.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-06-23
|
10KB
|
375 lines
///////////////////////////////////////////////////////////////////////////////
//
// File: FlushPort.c
//
// Project: MacHack 2000 - Vertigo!
// Authors: Darrin Cardani, Drew Thaler, Ed Wynne
//
// Date: 06/23/2000 (written entirely during the conference!)
//
///////////////////////////////////////////////////////////////////////////////
#include <alloca.h>
#include <DriverServices.h>
#include <Types.h>
#include <Memory.h>
#include <Quickdraw.h>
#include <QDOffscreen.h>
#include <Fonts.h>
#include <Events.h>
#include <Menus.h>
#include <Windows.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <OSUtils.h>
#include <Sound.h>
#include <string.h>
#include <ToolUtils.h>
#include "DebugUtils.h"
#include "DrawingUtils.h"
#include "DrawingFunctions.h"
#include "FlushPort.h"
// • Prototypes
void main(void);
void InitializeToolbox(void);
// ----------------------------------------------------------------------------------
// main
// ----------------------------------------------------------------------------------
/*
void main(void)
{
// Set up the mac application.
InitializeToolbox();
// Create a couple of empty windows for show.
Rect windowRects[] = { {300,450,600,800}, {100,100,450,600}, {240,444,464,989}, {256,196,645,732} };
int numWindows = sizeof(windowRects) / sizeof(Rect);
WindowPtr *windowList = (WindowPtr*)alloca(sizeof(WindowPtr)*numWindows);
RegionList windowRegions;
for (int i=0; i<numWindows; ++i)
{
windowList[i] = NewCWindow(NULL,&windowRects[i],"\pWindow",true,documentProc,(WindowPtr)-1L,false,0);
windowRegions.Add(((WindowPeek)windowList[i])->strucRgn,true);
}
// Fetch the color window manager port.
CGrafPtr wmgrPort;
GetCWMgrPort(&wmgrPort);
// Allocate a whole mess of GWorlds. Error checking is for pussies.
StGWorld screenGWorld(wmgrPort);
StGWorld dropShadowWorld(wmgrPort);
StGWorld preShiftWorld(wmgrPort);
StGWorld scratchWorld(wmgrPort);
StGWorld postShiftWorld(wmgrPort);
// Grab an image of the current screen.
CopyPortToGWorld(wmgrPort,screenGWorld);
// Create a window the same size as the screen, and display it. This doesn't
// get us above floaters (like the stupid control strip), but it's fine for a test app.
StHideMenuBar hideMenuBar;
WindowPtr screenWindow = NewCWindow(NULL,&wmgrPort->portRect,"\pdrew's screen display",true,plainDBox,(WindowPtr)-1L,false,0);
// Create a composite GWord for the output. Alternatively, composite onscreen for debugg.
//StGWorld compositeWorld(wmgrPort);
GWorldPtr compositeWorld = (CGrafPtr)screenWindow;
{
// For debugging, erase the composite world to black.
{
StSetGWorld setPort(compositeWorld);
BackColor(blackColor);
EraseRect(&((CGrafPtr)compositeWorld)->portRect);
}
// Time to doctor the screenshot with our code. For the test app,
// we do the whole damn thing at once.
StRegion maskRegion(*screenGWorld.PortRect());
// Lay down some drop shadows.
RenderDropShadows(screenGWorld,dropShadowWorld,maskRegion,windowRegions);
// Loop across each window to do the red-shifting.
const float maxDepth = 10;
for (int i=-1; i<numWindows; ++i)
{
int windowIndex = numWindows - i;
float depthToUse = maxDepth - (maxDepth / windowIndex);
int inPlane = (windowIndex == 1);
StRegion rgn;
// Figure out which region we're starting with.
if (i == -1)
{
rgn = wmgrPort->portRect;
depthToUse = 10;
}
else
{
rgn = windowRegions[i];
}
// Subtract out all windows above it, and clip to our mask.
for (int j=i+1; j<numWindows; ++j)
rgn -= windowRegions[j];
rgn &= maskRegion;
// Skip if we've eliminated everything.
if (rgn.IsEmpty()) continue;
// Red shift if it's not in the plane... otherwise just copy it wholesale.
if (!inPlane)
{
CopyRegionForRedShifting(dropShadowWorld,preShiftWorld,rgn);
RedShiftAndBlur(preShiftWorld,scratchWorld,postShiftWorld,rgn,depthToUse);
CopyIntoComposite(postShiftWorld,compositeWorld,rgn);
}
else
{
CopyIntoComposite(dropShadowWorld,compositeWorld,rgn);
}
// Blit our composited image back into visible space.
CopyGWorldToPort(compositeWorld,screenWindow,maskRegion);
// Wait for a mousedown. We WNE so drew can grab a screen shot.
while (!Button()) { EventRecord ev; WaitNextEvent(everyEvent,&ev,0,NULL); SystemTask(); }
while (Button()) {}
}
}
// Hang out for a while.
for (int i=0; i<numWindows; ++i)
DisposeWindow(windowList[i]);
DisposeWindow(screenWindow);
}
// ----------------------------------------------------------------------------------
// InitializeToolbox
// ----------------------------------------------------------------------------------
void InitializeToolbox(void)
{
OSErr err;
SysEnvRec theWorld;
// Test the computer to be sure we can do color.
// If not we would crash, which would be bad.
// If we can’t run, just beep and exit.
// (•• can you tell this code was descended from SillyBalls? ••)
err = SysEnvirons(1, &theWorld);
if (theWorld.hasColorQD == false) {
SysBeep(50);
ExitToShell();
}
// Initialize all the needed managers.
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
InitCursor();
GetDateTime((unsigned long*) &qd.randSeed);
if ((UInt32)UpTime != 0)
qd.randSeed ^= UpTime().lo;
}
*/
// -- When passed a zero-based index, this function passes back the indicated
// -- menu's rect (0=top-most, n-1=bottom-most). Returns false if no more menus.
#define kMBSaveLoc 0x0B5C
#define kLengthCookie 0x001C
Boolean MenuSnitch(short menuIndex, Rect *menuRect);
Boolean MenuSnitch(short menuIndex, Rect *menuRect)
{
Boolean result = false;
short menuCount = 0;
Handle mbSaveLoc = * (Handle *) kMBSaveLoc;
if (mbSaveLoc)
menuCount = (** (short **) mbSaveLoc) / kLengthCookie;
if ((menuIndex >= 0) && (menuIndex < menuCount))
{
(*menuRect) = * (Rect *) (*mbSaveLoc +((menuIndex + 1) * kLengthCookie));
result = true;
}
return(result);
} // -- MenuSnitch
extern GWorldPtr dropShadowWorld;
extern GWorldPtr preShiftWorld;
extern GWorldPtr scratchWorld;
extern GWorldPtr postShiftWorld;
extern GWorldPtr gStageBuffer;
void RenderBufferOntoScreen(GWorldPtr srcWorld,GWorldPtr dstWorld,Rect *inRect,RgnHandle inMask)
{
THz oldZone = GetZone();
SetZone(SystemZone());
StRegion fullScreen(dstWorld->portRect);
// Build a list of the window regions, in back-to-front order. We don't
// include the desktop in this list.
RegionList windowRegions;
bool windowListChanged = false;
BuildWindowList(windowRegions,windowListChanged);
if (windowListChanged)
{
// Re-blit the entire screen.
*inRect = dstWorld->portRect;
CopyRgn(fullScreen,inMask);
}
// Lay down some fresh drop shadows.
RenderDropShadows(srcWorld,dropShadowWorld,inMask,windowRegions);
// Loop across each window to do the red-shifting.
const float maxDepth = 10;
int numWindows = windowRegions.GetCount();
for (int i=-1; i<numWindows; ++i)
{
int windowIndex = numWindows - i;
int depthToUse = maxDepth - (maxDepth / windowIndex);
int inPlane = (windowIndex <= 2);
StRegion rgn;
// Figure out which region we're starting with.
if (i == -1)
{
rgn = dstWorld->portRect;
depthToUse = 10;
}
else
{
rgn = windowRegions[i];
}
// Subtract out all windows above it, and clip to our mask.
for (int j=i+1; j<numWindows; ++j)
rgn -= windowRegions[j];
rgn &= inMask;
// Skip if we've eliminated everything.
if (rgn.IsEmpty()) continue;
// Red shift if it's not in the plane... otherwise just copy it wholesale.
if (!inPlane)
{
CopyRegionForRedShifting(dropShadowWorld,preShiftWorld,rgn);
RedShiftAndBlur(preShiftWorld,scratchWorld,postShiftWorld,rgn,depthToUse);
CopyIntoComposite(postShiftWorld,gStageBuffer,rgn);
}
else
{
CopyIntoComposite(dropShadowWorld,gStageBuffer,rgn);
}
}
if (numWindows > 0)
DisposeRgn(windowRegions[numWindows-1]);
CopyGWorldToGWorld(gStageBuffer,dstWorld);
SetZone(oldZone);
}
// --------------------------------------------------------
// Single-app window list
void
BuildWindowList(RegionList &windowList, bool &windowListChanged)
{
static UInt32 oldList[1024] = {0};
static UInt32 newList[1024] = {0};
UInt32 *newListCursor = &newList[0];
UInt32 remaining = 1024;
ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
ProcessSerialNumber thisProcess = {0,0};
Boolean same = false;
// For now we only do the front app's windows. Yeah this is lame and sucks, but it'll
// make us work for now.
GetCurrentProcess(&thisProcess);
if ((SameProcess(&thisProcess,¤tProcess,&same) != noErr) || !same)
{
windowListChanged = false;
return;
}
// Since it's close to demo time...
windowListChanged = true;
// Grab the menu bar and the active menus.
{
StRegion rgn;
GDHandle mainDevice = GetMainDevice();
SetRectRgn(rgn,mainDevice[0]->gdRect.left,mainDevice[0]->gdRect.top,mainDevice[0]->gdRect.right,mainDevice[0]->gdRect.top+GetMBarHeight());
// Add the current menu region here.
Rect menuRect;
short index = 0;
while (MenuSnitch(index++,&menuRect))
rgn += menuRect;
windowList.Add(rgn,true);
}
// Grab the visible windows in front-to-back order.
WindowPeek window = (*(WindowPeek*)0x9D6);
while ((window != NULL) && (window != (WindowPeek)-1L))
{
if (window->visible)
{
windowList.Add(window->strucRgn,false);
*(newListCursor++) = (UInt32)window;
*(newListCursor++) = *(UInt32*)&window->strucRgn[0]->rgnBBox.top;
*(newListCursor++) = *(UInt32*)&window->strucRgn[0]->rgnBBox.bottom;
remaining -= 3;
dprintf(kDConPrefix "Registering window %08X %08X %08X\n", *(newListCursor-3), *(newListCursor-2), *(newListCursor-1));
}
window = window->nextWindow;
}
// See if the window ordering or locations has changed since our last blit.
BlockZero(newListCursor,remaining*4);
if (!memcmp(oldList,newList,1024*4))
{
windowListChanged = true;
BlockMoveData(newList,oldList,1024*4);
}
// Swap the windows in the list so that they're back-to-front.
int count = windowList.GetCount();
for (int i=0; i<count/2; ++i)
{
RgnHandle temp = windowList[i];
windowList[count-i-1] = windowList[i];
windowList[count-i-1] = temp;
}
}